package aufgabenserie_2;

import java.math.BigInteger;
import java.util.Random;

public class AliceORBob {


	public void startCommunication(BigInteger g, BigInteger n, AliceORBob theOther, boolean useSquareMultiply){
		BigInteger g_x_mod_n;
		BigInteger k_AB;
		int my_Secret = -1;
		BigInteger g_y_mod_n = null;
		

		
		my_Secret = (int) ( (Integer.MAX_VALUE>>16)* Math.random());
		System.out.println("x: "+my_Secret);

		if(useSquareMultiply == false){
			g_x_mod_n = g.pow(my_Secret).mod(n);
			g_y_mod_n = theOther.receive(n, g, g_x_mod_n, useSquareMultiply);
			System.out.println("|<--|\nreceived\ng_y_mod_n "+g_y_mod_n);
			k_AB = g_y_mod_n.pow(my_Secret).mod(n);
		}else{
			BigInteger my_Secret_big = new BigInteger( new Integer(my_Secret).toString());
			g_x_mod_n = squareAndMultiply(g, my_Secret_big, n);
			g_y_mod_n = theOther.receive(n, g, g_x_mod_n, useSquareMultiply);
			System.out.println("|<--|\nreceived\ng_y_mod_n "+g_y_mod_n);
			k_AB = squareAndMultiply(g_y_mod_n, my_Secret_big, n);
		}
		
		
		
		
		System.out.println("-------------->k_AB: "+k_AB);

	}
	
	public BigInteger receive(BigInteger n, BigInteger g, BigInteger g_x_mod_n, boolean useSquareMultiply){
		System.out.println("|-->|\nreceived\n(n: "+n+",\ng: "+g+",\ng_x_mod_n: "+g_x_mod_n+")");
		int other_Secret = (int) ( (Integer.MAX_VALUE>>16) * Math.random());
		System.out.println("y: "+other_Secret);
		BigInteger k_AB;
		
		BigInteger g_y_mod_n;
		if(useSquareMultiply == false){
			g_y_mod_n = g.pow(other_Secret).mod(n);
			k_AB = g_x_mod_n.pow(other_Secret).mod(n);
		}else{
			BigInteger other_Secret_big = new BigInteger( new Integer(other_Secret).toString());
			g_y_mod_n = squareAndMultiply(g, other_Secret_big, n);
			k_AB = squareAndMultiply(g_x_mod_n, other_Secret_big, n);
		}
		
		
		System.out.println("-------------->k_AB: "+k_AB);
		
		return g_y_mod_n;
	}
	
	public static BigInteger squareAndMultiply(BigInteger e, BigInteger x, BigInteger n){     	
		BigInteger r = new BigInteger("1");

    	for(int i=x.bitLength()-1; i >= 0 ; i--) {
    		r = r.multiply(r).mod(n);
    		if(x.testBit(i)) r = r.multiply(e).mod(n);
    	}
    	return r;    	
    }
	
	
}
